diff --git a/web/modals/threads/notifications/enum-settings-option-info.css b/web/components/enum-settings-option-info.css
similarity index 100%
rename from web/modals/threads/notifications/enum-settings-option-info.css
rename to web/components/enum-settings-option-info.css
diff --git a/web/modals/threads/notifications/enum-settings-option-info.react.js b/web/components/enum-settings-option-info.react.js
similarity index 92%
rename from web/modals/threads/notifications/enum-settings-option-info.react.js
rename to web/components/enum-settings-option-info.react.js
index eb8ef4383..dbcb88474 100644
--- a/web/modals/threads/notifications/enum-settings-option-info.react.js
+++ b/web/components/enum-settings-option-info.react.js
@@ -1,37 +1,37 @@
// @flow
import classnames from 'classnames';
import * as React from 'react';
-import SWMansionIcon from '../../../SWMansionIcon.react';
+import SWMansionIcon from '../SWMansionIcon.react';
import css from './enum-settings-option-info.css';
type Props = {
+valid: boolean,
+children: React.Node,
};
function EnumSettingsOptionInfo(props: Props): React.Node {
const { valid, children } = props;
const optionInfoClasses = React.useMemo(
() =>
classnames(css.optionInfo, {
[css.optionInfoInvalid]: !valid,
}),
[valid],
);
const icon = React.useMemo(
() => ,
[valid],
);
return (
{icon}
{children}
);
}
export default EnumSettingsOptionInfo;
diff --git a/web/modals/threads/notifications/enum-settings-option.css b/web/components/enum-settings-option.css
similarity index 100%
rename from web/modals/threads/notifications/enum-settings-option.css
rename to web/components/enum-settings-option.css
diff --git a/web/modals/threads/notifications/enum-settings-option.react.js b/web/components/enum-settings-option.react.js
similarity index 95%
rename from web/modals/threads/notifications/enum-settings-option.react.js
rename to web/components/enum-settings-option.react.js
index 9a8305b4d..1cc865ef3 100644
--- a/web/modals/threads/notifications/enum-settings-option.react.js
+++ b/web/components/enum-settings-option.react.js
@@ -1,53 +1,53 @@
// @flow
import classnames from 'classnames';
import * as React from 'react';
-import Radio from '../../../components/radio.react';
-import EnumSettingsOptionInfo from './enum-settings-option-info.react';
+import EnumSettingsOptionInfo from './enum-settings-option-info.react.js';
import css from './enum-settings-option.css';
+import Radio from './radio.react';
type Props = {
+selected: boolean,
+onSelect: () => void,
+icon: React.Node,
+title: string,
+statements: $ReadOnlyArray<{
+statement: string,
+isStatementValid: boolean,
}>,
};
function EnumSettingsOption(props: Props): React.Node {
const { icon, title, statements, selected, onSelect } = props;
const descriptionItems = React.useMemo(
() =>
statements.map(({ statement, isStatementValid }) => (
{statement}
)),
[statements],
);
const optionContainerClasses = React.useMemo(
() =>
classnames(css.optionContainer, {
[css.optionContainerSelected]: selected,
}),
[selected],
);
return (
{icon}
{title}
{descriptionItems}
);
}
export default EnumSettingsOption;
diff --git a/web/modals/threads/notifications/notifications-modal.react.js b/web/modals/threads/notifications/notifications-modal.react.js
index 6641778ef..e90e7a48b 100644
--- a/web/modals/threads/notifications/notifications-modal.react.js
+++ b/web/modals/threads/notifications/notifications-modal.react.js
@@ -1,192 +1,192 @@
// @flow
import * as React from 'react';
import {
updateSubscription,
updateSubscriptionActionTypes,
} from 'lib/actions/user-actions';
import { threadInfoSelector } from 'lib/selectors/thread-selectors';
import {
useServerCall,
useDispatchActionPromise,
} from 'lib/utils/action-utils';
import {
assetCacheURLPrefix,
backgroundNotificationsIllustrationFileName,
backgroundNotificationsIllustrationHeight,
backgroundNotificationsIllustrationWidth,
badgeOnlyNotificationsIllustrationFileName,
badgeOnlyNotificationsIllustrationHeight,
badgeOnlyNotificationsIllustrationWidth,
focusedNotificationsIllustrationFileName,
focusedNotificationsIllustrationHeight,
focusedNotificationsIllustrationWidth,
} from '../../../assets.js';
import Button from '../../../components/button.react';
+import EnumSettingsOption from '../../../components/enum-settings-option.react';
import { useSelector } from '../../../redux/redux-utils';
import Modal from '../../modal.react';
-import EnumSettingsOption from './enum-settings-option.react';
import css from './notifications-modal.css';
type NotificationSettings = 'focused' | 'badge-only' | 'background';
type Props = {
+threadID: string,
+onClose: () => void,
};
function NotificationsModal(props: Props): React.Node {
const { onClose, threadID } = props;
const threadInfo = useSelector(state => threadInfoSelector(state)[threadID]);
const { subscription } = threadInfo.currentUser;
const initialThreadSetting = React.useMemo(() => {
if (!subscription.home) {
return 'background';
}
if (!subscription.pushNotifs) {
return 'badge-only';
}
return 'focused';
}, [subscription.home, subscription.pushNotifs]);
const [
notificationSettings,
setNotificationSettings,
] = React.useState(initialThreadSetting);
const onFocusedSelected = React.useCallback(
() => setNotificationSettings('focused'),
[],
);
const onBadgeOnlySelected = React.useCallback(
() => setNotificationSettings('badge-only'),
[],
);
const onBackgroundSelected = React.useCallback(
() => setNotificationSettings('background'),
[],
);
const isFocusedSelected = notificationSettings === 'focused';
const focusedItem = React.useMemo(() => {
const statements = [
{ statement: 'Banner notifs', isStatementValid: true },
{ statement: 'Badge count', isStatementValid: true },
{ statement: 'Lives in Focused tab', isStatementValid: true },
];
const icon = (
);
return (
);
}, [isFocusedSelected, onFocusedSelected]);
const isFocusedBadgeOnlySelected = notificationSettings === 'badge-only';
const focusedBadgeOnlyItem = React.useMemo(() => {
const statements = [
{ statement: 'Banner notifs', isStatementValid: false },
{ statement: 'Badge count', isStatementValid: true },
{ statement: 'Lives in Focused tab', isStatementValid: true },
];
const icon = (
);
return (
);
}, [isFocusedBadgeOnlySelected, onBadgeOnlySelected]);
const isBackgroundSelected = notificationSettings === 'background';
const backgroundItem = React.useMemo(() => {
const statements = [
{ statement: 'Banner notifs', isStatementValid: false },
{ statement: 'Badge count', isStatementValid: false },
{ statement: 'Lives in Background tab', isStatementValid: true },
];
const icon = (
);
return (
);
}, [isBackgroundSelected, onBackgroundSelected]);
const dispatchActionPromise = useDispatchActionPromise();
const callUpdateSubscription = useServerCall(updateSubscription);
const onClickSave = React.useCallback(() => {
dispatchActionPromise(
updateSubscriptionActionTypes,
callUpdateSubscription({
threadID: threadID,
updatedFields: {
home: notificationSettings !== 'background',
pushNotifs: notificationSettings === 'focused',
},
}),
);
onClose();
}, [
callUpdateSubscription,
dispatchActionPromise,
notificationSettings,
onClose,
threadID,
]);
return (
{focusedItem}
{focusedBadgeOnlyItem}
{backgroundItem}
);
}
export default NotificationsModal;